package edu.manju.mimi.core;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * <h4>mimi-core</h4>
 * <p>Restful api的返回类型</p>
 *
 * @author : Lebei(lebei163@163.com)
 * @date : 2023-02-24 19:42
 **/

/**
 * 响应操作结果
 * <pre>
 *  {
 *         code： 响应码，
 *      message： 响应消息，
 *         data： 响应数据
 *  }
 * </pre>
 *
 * <p>
 * 响应码：
 * <ul>
 * <li> 0，成功；
 * <li> 4xx，前端错误，说明前端开发者需要重新了解后端接口使用规范：
 * <ul>
 * <li> 401，参数错误，即前端没有传递后端需要的参数；
 * <li> 402，参数值错误，即前端传递的参数值不符合后端接收范围。
 * </ul>
 * <li> 5xx，后端错误，除501外，说明后端开发者应该继续优化代码，尽量避免返回后端错误码：
 * <ul>
 * <li> 501，验证失败，即后端要求用户登录；
 * <li> 502，系统内部错误，即没有合适命名的后端内部错误；
 * <li> 503，业务不支持，即后端虽然定义了接口，但是还没有实现功能；
 * <li> 504，更新数据失效，即后端采用了乐观锁更新，而并发更新时存在数据更新失效；
 * <li> 505，更新数据失败，即后端数据库更新失败（正常情况应该更新成功）。
 * </ul>
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class R<T> {
    private Integer code;
    private String message;
    private T data;

    // success
    public static <T> R<T> ok() {
        return new R<>(0, "success", null);
    }

    public static <T> R<T> ok(T data) {
        return new R<>(0, "success", data);
    }

    public static <T> R<T> ok(T data, String message) {
        return new R<>(0, message, data);
    }

    // failure
    public static <T> R<T> fail() {
        return new R<>(-1, "fail", null);
    }

    public static <T> R<T> fail(String message) {
        return new R<>(-1, message, null);
    }

    public static <T> R<T> fail(Integer code, String message) {
        return new R<>(code, message, null);
    }

    public static <T> R<T> badArgument() {
        return fail(401, "invalid parameters");
    }

    public static <T> R<T> badArgumentValue() {
        return fail(402, "invalid value");
    }

    public static <T> R<T> unlogin() {
        return fail(501, "No login");
    }

    public static <T> R<T> serious() {
        return fail(502, "internal errors");
    }

    public static <T> R<T> unsupported() {
        return fail(503, "unsupported");
    }

    public static <T> R<T> updatedDateExpired() {
        return fail(504, "expired when updating data");
    }

    public static <T> R<T> updatedDataFailed() {
        return fail(505, "failed when updating data");
    }
}
